﻿using System;
using System.Runtime.Serialization;

namespace SharpGL.SceneGraph
{

    /// <summary>
    /// a texture coordinate.
    /// </summary>
    [DataContract()]
    public struct UV
    {
        #region Private Fields

        /// <summary>
        /// The u value.
        /// </summary>
        [DataMember()]
        private float u;

        /// <summary>
        /// The point value.
        /// </summary>
        [DataMember()]
        private float v;

        #endregion Private Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UV"/> struct.
        /// </summary>
        /// <param name="u">The u.</param>
        /// <param name="point">The point.</param>
        public UV(float u, float v) 
        { 
            this.u = u; 
            this.v = v; 
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UV"/> struct.
        /// </summary>
        /// <param name="u">The u.</param>
        /// <param name="point">The point.</param>
        public UV(UV uv) 
        {
            this.u = uv.u;
            this.v = uv.v; 
        }

        #endregion Constructors

        #region Public Methods

        public override int GetHashCode()
        {
            return this.u.GetHashCode() ^ this.v.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is UV))
            {
                return false;
            }

            return Equals(this, (UV)obj);
        }

        public bool Equals(UV uv)
        {
            return Equals(this, uv);
        }

        public static bool Equals(UV uv1, UV uv2)
        {
            return uv1.u.Equals(uv2.u) && uv1.v.Equals(uv2.v);
        }

        public override string ToString()
        {
            return "(" + this.u + ", " + this.v + ")";
        }

        #endregion Public Methods

        #region Public Operators

        public static bool operator ==(UV uv1, UV uv2)
        {
            return uv1.Equals(uv2);
        }

        public static bool operator !=(UV uv1, UV uv2)
        {
            return !uv1.Equals(uv2);
        }

        public static implicit operator float[](UV uv)
        {
            return new float[] { uv.u, uv.v };
        }

        #endregion Public Operators

        #region Public Properties

        /// <summary>
        /// Gets or sets the U.
        /// </summary>
        /// <value>
        /// The U.
        /// </value>
        public float U
        {
            get { return this.u; }
            set { this.u = value; }
        }

        /// <summary>
        /// Gets or sets the V.
        /// </summary>
        /// <value>
        /// The V.
        /// </value>
        public float V
        {
            get { return this.v; }
            set { this.v = value; }
        }

        #endregion Public Properties
    }
}
